using System.Reflection;
using AutoMapper;
using XUCore.Helpers;
using XUCore.Extensions;
using System;
using System.Linq;

namespace XUCore.Ddd.Domain
{
    /// <summary>
    /// 创建对象映射
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    public abstract class CreateMap<TSource> : ICreateMap<TSource>
    {
        public virtual void Mapping(Profile profile) => profile.CreateMap(typeof(TSource), GetType(), MemberList.None);
    }
    /// <summary>
    /// Mapper映射，自定义映射请先实现 Mapping(Profile profile) 方法
    /// </summary>
    /// <typeparam name="TSource">源数据对象</typeparam>
    public interface ICreateMap<TSource>
    {
        void Mapping(Profile profile) => profile.CreateMap(typeof(TSource), GetType(), MemberList.None);
    }

    /// <summary>
    /// Mapper映射设置 <see cref="Profile"/>
    /// </summary>
    public abstract class MapFromProfile : Profile
    {
        /// <summary>
        /// Mapper映射设置 <see cref="Profile"/>
        /// </summary>
        /// <param name="assemblyFilter">程序集名称检索，缩小范围在当前项目内，如：XUCore.NetCore ，不带dll</param>
        public MapFromProfile(string assemblyFilter) => ApplyMappingsFromAssembly(assemblyFilter);

        /// <summary>
        /// 配置 IMapFrom
        /// </summary>
        /// <param name="assemblyFilter">程序集名称检索，缩小范围在当前项目内，如：XUCore.NetCore ，不带dll</param>
        public virtual void ApplyMappingsFromAssembly(string assemblyFilter)
        {
            var types = Reflection.GetCurrentProjectAssemblies(assemblyFilter)
                .SelectMany(c =>
                    c.GetTypes(type => type.IsAbstract == false && type.GetInterfaces().Any(i => i.IsParticularGeneric(typeof(ICreateMap<>))))
                )
                .ToList();

            foreach (var type in types)
            {
                var instance = Activator.CreateInstance(type);
                type.GetMethod("Mapping")?.Invoke(instance, new object[] { this });
            }
        }
    }
}